package com.alinesno.cloud.gateway.core.dispather.socket;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alinesno.cloud.gateway.core.dispather.socket.channel.ChannelCache;
import com.alinesno.cloud.gateway.core.dispather.socket.channel.ServerChannelInitializer;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * Socket接口配置
 * 
 * @author LuoAnDong
 * @since 2019年9月21日 下午7:46:03
 */
@Configuration
public class NettyConfigation {

	@Value("${aliesno.gateway.socket.boss.thread.count:2}")
	private int bossCount;

	@Value("${aliesno.gateway.socket.worker.thread.count:2}")
	private int workerCount;

	@Value("${aliesno.gateway.socket.keepalive:true}")
	private boolean keepAlive;

	@Value("${aliesno.gateway.socket.backlog:100}")
	private int backlog;

	@SuppressWarnings("unchecked")
	public ServerBootstrap bootstrap(ServerChannelInitializer serverChannelInitializer) {
		ServerBootstrap b = new ServerBootstrap();

		b.group(bossGroup(), workerGroup()).channel(NioServerSocketChannel.class)
			.handler(new LoggingHandler(LogLevel.DEBUG)) 
			.childHandler(serverChannelInitializer);

		Map<ChannelOption<?>, Object> tcpChannelOptions = tcpChannelOptions();
		Set<ChannelOption<?>> keySet = tcpChannelOptions.keySet();

		for (@SuppressWarnings("rawtypes")
		ChannelOption option : keySet) {
			b.option(option, tcpChannelOptions.get(option));
		}

		return b;
	}
	
	@Bean
	public Map<ChannelOption<?>, Object> tcpChannelOptions() {
		Map<ChannelOption<?>, Object> options = new HashMap<ChannelOption<?>, Object>();
		
		// JDK8中无效 
		// options.put(ChannelOption.SO_KEEPALIVE, keepAlive);
		
		options.put(ChannelOption.SO_BACKLOG, backlog);
		return options;
	}

	@Bean(name = "bossGroup", destroyMethod = "shutdownGracefully")
	public NioEventLoopGroup bossGroup() {
		return new NioEventLoopGroup(bossCount);
	}

	@Bean(name = "workerGroup", destroyMethod = "shutdownGracefully")
	public NioEventLoopGroup workerGroup() {
		return new NioEventLoopGroup(workerCount);
	}


	@Bean
	public ChannelCache channelRepository() {
		return new ChannelCache();
	}

}
